package org.libarae.communication.request;

import java.io.ByteArrayOutputStream;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.libarae.communication.HTTPUtils;
import org.libarae.communication.XmlParseException;
import org.libarae.communication.common.Book;
import org.libarae.communication.common.Book.BookStatus;
import org.libarae.communication.common.Type;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class BookSearchRequest extends Request {
	private int mSearchPageNumber = 0;
	private int mSearchPageSize = 0;	
	
	private String mTitle = "", mIsbn= "", mAuthor= "", mYear= "", mOmniSearch= "", mSummary= "", mPublisher= "";

	private Book.BookStatus mStatus;
	
	public BookSearchRequest(){
		super(Type.BOOK_SEARCH);
	}
	
	public BookSearchRequest(int searchPageNumber, int searchPageSize){
		super(Type.BOOK_SEARCH);
		this.mSearchPageNumber = searchPageNumber;
		this.mSearchPageSize = searchPageSize;
	}
	
	public BookSearchRequest(int searchPageNumber, int searchPageSize, String title, String isbn, String author, String year, String omniSearch, Book.BookStatus status, String summary, String pub){
		super(Type.BOOK_SEARCH);
		this.mSearchPageNumber = searchPageNumber;
		this.mSearchPageSize = searchPageSize;
		this.mTitle = title;
		this.mIsbn = isbn;
		this.mAuthor = author;
		this.mYear = year;
		this.mOmniSearch = omniSearch;
		this.mStatus = status;
		this.mSummary = summary;
		this.mPublisher = pub;
	}

	@Override
	public String createXML() throws XmlParseException {
		Document doc;
		try{
			//setup the factory to build the xml
			DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
			doc = documentBuilder.newDocument();
		}
		catch (Exception e) {
			throw new XmlParseException("Error creating XML Builder",e);
		}
		
		//create the xml
		Element rootElement = doc.createElement("type");
		rootElement.setAttribute("typeID", super.getType()+"");
		doc.appendChild(rootElement);
		//set the accessKey
		Element node = doc.createElement("mAccessKey");
		node.setTextContent(getAccessKey());
		rootElement.appendChild(node);

		node = doc.createElement("mSearchPageNumber");
		node.setTextContent(mSearchPageNumber+"");
		rootElement.appendChild(node);
		
		node = doc.createElement("mSearchPageSize");
		node.setTextContent(mSearchPageSize+"");
		rootElement.appendChild(node);
		
		node = doc.createElement("mTitle");
		node.setTextContent(mTitle);
		rootElement.appendChild(node);
		
		node = doc.createElement("mIsbn");
		node.setTextContent(mIsbn);
		rootElement.appendChild(node);
		
		node = doc.createElement("mAuthor");
		node.setTextContent(mAuthor);
		rootElement.appendChild(node);
		
		node = doc.createElement("mYear");
		node.setTextContent(mYear);
		rootElement.appendChild(node);
		
		node = doc.createElement("mOmniSearch");
		node.setTextContent(mOmniSearch);
		rootElement.appendChild(node);
		
		node = doc.createElement("mSummary");
		node.setTextContent(mSummary);
		rootElement.appendChild(node);
		
		node = doc.createElement("mPublisher");
		node.setTextContent(mPublisher);
		rootElement.appendChild(node);
		
		node = doc.createElement("mStatus");
		if(mStatus != null)
			node.setTextContent(mStatus.ordinal()+"");
		else
			node.setTextContent("-1");
		rootElement.appendChild(node);

		
		//export the xml to a string
		String output = null;
		try {
			ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream();
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(byteArrayOutput);
			transformer.transform(source, result);
			output = byteArrayOutput.toString();
		}
		catch (Exception e) {
			throw new XmlParseException("Error outputting XML to string", e);
		}
		
		//return the string
		return output;
	}

	@Override
	public void decodeXML(Document doc) {
		// get the document root and node list
		Element root = doc.getDocumentElement();
		NodeList nodeList = root.getChildNodes();
		
		//set type
		super.setType(Type.BOOK_SEARCH);

		// set all of the nodes in their proper places
		for (int i = 0; i < nodeList.getLength(); i++) {			
			// find what node we have
			String nodeName = nodeList.item(i).getNodeName();
			if (nodeName.equals("mAccessKey")) {
				setAccessKey(nodeList.item(i).getTextContent());
			}
			else if (nodeName.equals("mSearchPageNumber")) {
				mSearchPageNumber = Integer.parseInt(nodeList.item(i).getTextContent());
			}
			else if (nodeName.equals("mSearchPageSize")) {
				mSearchPageSize = Integer.parseInt(nodeList.item(i).getTextContent());
			}
			else if (nodeName.equals("mTitle")) {
				mTitle = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mIsbn")) {
				mIsbn = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mAuthor")) {
				mAuthor = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mYear")) {
				mYear = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mOmniSearch")) {
				mOmniSearch = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mSummary")) {
				mSummary = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mPublisher")) {
				mPublisher = nodeList.item(i).getTextContent();
			}
			else if (nodeName.equals("mStatus")) {
				int status = Integer.parseInt(nodeList.item(i).getTextContent());
				switch(status){
					case -1:
						mStatus = null;
						break;
					case 0:
						mStatus = BookStatus.CHECKED_OUT;
					break;
					case 1:
						mStatus = BookStatus.PENDING;
					break;
					case 2:
						mStatus = BookStatus.AVAILABLE;
					break;
				}
			}			
			else {
				System.err.println("Unknow field in object XML: " + nodeName);
			}
		}
	}
	
	public String getTitle() {
		return mTitle;
	}

	public void setTitle(String mTitle) {
		this.mTitle = mTitle;
	}

	public String getIsbn() {
		return mIsbn;
	}

	public void setIsbn(String mIsbn) {
		this.mIsbn = mIsbn;
	}

	public String getAuthor() {
		return mAuthor;
	}

	public void setAuthor(String mAuthor) {
		this.mAuthor = mAuthor;
	}

	public String getYear() {
		return mYear;
	}

	public void setYear(String mYear) {
		this.mYear = mYear;
	}

	public String getOmniSearch() {
		return mOmniSearch;
	}

	public void setOmniSearch(String mOmniSearch) {
		this.mOmniSearch = mOmniSearch;
	}

	public Book.BookStatus getStatus() {
		return mStatus;
	}

	public void setStatus(Book.BookStatus mStatus) {
		this.mStatus = mStatus;
	}

	public int getSearchPageNumber() {
		return mSearchPageNumber;
	}

	public void setSearchPageNumber(int mSearchPageNumber) {
		this.mSearchPageNumber = mSearchPageNumber;
	}

	public int getSearchPageSize() {
		return mSearchPageSize;
	}

	public void setSearchPageSize(int mSearchPageSize) {
		this.mSearchPageSize = mSearchPageSize;
	}

	public String getSummary() {
		return mSummary;
	}

	public void setSummary(String mSummary) {
		this.mSummary = mSummary;
	}

	public String getPublisher() {
		return mPublisher;
	}

	public void setPublisher(String mPublisher) {
		this.mPublisher = mPublisher;
	}	
	
	@Override
	public String creatGET() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void decodeGET(String postMessage) {
		Map<String, String> map = HTTPUtils.getParams(postMessage);
		if(map.containsKey("mOmniSearch"))
			setOmniSearch(map.get("mOmniSearch"));
		else
			setOmniSearch("");
		this.mSearchPageSize = 10;//Fixed for html
		
		if(map.containsKey("mSearchPageNumber"))//If it was passed
			this.mSearchPageNumber = Integer.parseInt(map.get("mSearchPageNumber"));
		else//Assume first page
			this.mSearchPageNumber = 0;
		
		setHtmlHelperMessage("Search:" + this.getOmniSearch() + "\nPage:" + this.mSearchPageNumber);
		
		//Set everything else to "", since book search dosn't handle null at all....Unless they added advanced options
		if(map.containsKey("mTitle"))
			setTitle(map.get("mTitle"));
		else
			setTitle("");
		
		if(map.containsKey("mIsbn"))
			setIsbn(map.get("mIsbn"));
		else
			setIsbn("");
		
		if(map.containsKey("mAuthor"))
			setAuthor(map.get("mAuthor"));
		else
			setAuthor("");

		if(map.containsKey("mYear"))
			setYear(map.get("mYear"));
		else
			setYear("");

		if(map.containsKey("mPublisher"))
			setYear(map.get("mPublisher"));
		else
			setYear("");

	}
}